2

记录unix网络编程的复习之路

简单回顾下socket连接过程


  • socket() --得到fd!

     功能:指定了协议族(IPv4、IPv6或unix)和套接口类型(字节流、数据报或原始套接口)。但并没有指定本地协议地址或远程协议地址。
     定义:int socket(int family, int type, int protocol);
     返回:出错:-1
            成功:套接口描述字 (socket file descriptor)(套接字)sockfd
  • bind() --我在哪个端口?

     功能:给套接口分配一个本地协议地址。
     定义:int bind(int sockfd, const struct sockaddr *my_addr, int addrlen);
  • connect() --Hello!

     功能:建立与TCP服务器的连接
     定义:int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
  • listen() --有人给我打电话吗?

     功能:将未连接主动套接口的转换为被动套接口,指示内核接受对该套接口的连接请求。
     定义:int listen(int sockfd, int backlog);
     参数:
         - sockfd调用socket函数返回的文件描述符(套接字).
         - 未完成连接队列和已完成连接队列的上限.
            - 未完成连接队列 : 服务端还未完成三次握手全部过程的一个队列.
            - 已完成连接队列 : 服务端已经完成三次握手全部过程的一个队列, 等待accept函数从这个队列中返回下一个(返回其实是取出, 该套接字不在已完成队列中了)套接字.
    
  • accept() --"Thank you for calling port 3490."

     功能:accept函数从listen的已完成连接队列中返回下一个已完成连接, 也就是对端的套接字, 一个新的套接字. 当已完成连接队列的下一个完成 
          连接是空, 那么accept函数将被阻塞.
     定义:int accept(int sockfd, struct sockaddr *cliaddr, int* addrlen);
     返回:调用成功时返回: 1. cliaddr: 客户进程的协议地址和地址大小 2. 新套接口描述字
  • send() 和 recv() --Talk to me, baby!
  • close() --滚开!

socket()和accept()返回的fd

举个栗子:

一个客户端和一个服务端连接,双方socket产生各自的c_sock_fd和s_sock_fd;
s_sock_fd进行bind和listen后,accept准备接受客户端的连接请求;c_sock_fd调用connect请求连接服务端;
服务端接到请求产生accept_fd,届时accept_fd和c_sock_fd两个套接字可以通讯,而s_sock_fd则可以关闭;
客户端关闭close(c_sock_fd)后,服务端关闭所有未关闭的fd,通讯彻底断开。
ps:服务端的socket产生的套接字只是用来监听的,不能直接用于发送接收数据。

魏什么
1.5k 声望14 粉丝

干饭人、干饭魂、干饭人干饭得用盆